package com.atsmart.app.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

import android.text.TextUtils;
import com.atsmart.app.utils.StringUtil;

public class HttpHelper {

	public static final int CREATE_MODE = 0;
	public static final int READ_MODE = 1;
	public static final int UPDATE_MODE = 2;
	public static final int DELETE_MODE = 3;

	private int CONNECTION_TIMEOUT =20000;
	private int READ_TIMEOUT = 20000;
	// private static int STREAM_BUFFER_SIZE =0; //4 * 1024;

	static {
	}

	public int getCONNECTION_TIMEOUT() {
		return CONNECTION_TIMEOUT;
	}

	public void setCONNECTION_TIMEOUT(int cONNECTION_TIMEOUT) {
		CONNECTION_TIMEOUT = cONNECTION_TIMEOUT;
	}

	public static int getReadMode() {
		return READ_MODE;
	}
	

	public int getREAD_TIMEOUT() {
		return READ_TIMEOUT;
	}

	public void setREAD_TIMEOUT(int rEAD_TIMEOUT) {
		READ_TIMEOUT = rEAD_TIMEOUT;
	}

	public HttpHelper() {

	}

	public HttpHelper(int inputSize) {
		// STREAM_BUFFER_SIZE=inputSize;
	}

	private int mode;
	private URL url;
	private Map<String, String> headerValues;
	private HttpURLConnection connection;
	private ByteArrayOutputStream inputBuffer;

	public HttpHelper createMode() {
		return mode(CREATE_MODE);
	}

	public HttpHelper readMode() {
		return mode(READ_MODE);
	}

	public HttpHelper updateMode() {
		return mode(UPDATE_MODE);
	}

	public HttpHelper deleteMode() {
		return mode(DELETE_MODE);
	}

	public HttpHelper mode(int mode) {
		this.mode = mode % 4;
		return this;
	}

	public HttpHelper url(String urlString) throws MalformedURLException {
		if (urlString != null) {
			url = new URL(urlString);
		}
		return this;
	}

	public HttpHelper url(URL url) {
		this.url = url;
		return this;
	}

	public HttpHelper header(String header, String value) {
		ensureHeaderValuesNotNull();
		headerValues.put(header, value);
		return this;
	}

	public HttpHelper body(InputStream stream) {
		inputBuffer = new ByteArrayOutputStream();
		byte[] buf = new byte[1024];
		int len;
		try {
			while ((len = stream.read(buf)) > -1) {
				inputBuffer.write(buf, 0, len);
			}
			
		} catch (IOException ex) {
			// Will not happen.
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	
		return this;
	}

	public void send() throws IOException {
		if (connection != null) {
//			connection.disconnect();
			connection = null;
		}
		if (this.url == null || StringUtil.isEmptyOrNull(this.url.getHost())) {// Url
																				// empty
			throw new MalformedURLException();
		}

		connection = (HttpURLConnection) url.openConnection();
		this.connection.setUseCaches(false);
//		this.connection.setDoInput(true);
		this.connection.setDoOutput(true);
		this.connection.setConnectTimeout(CONNECTION_TIMEOUT);
		this.connection.setReadTimeout(READ_TIMEOUT);

		switch (mode) {
		case CREATE_MODE:
			connection.setRequestMethod("POST");
			break;
		case READ_MODE:
			connection.setRequestMethod("GET");
			break;
		case UPDATE_MODE:
			connection.setRequestMethod("POST");
			connection.addRequestProperty("X-OP", "Update");
			break;
		case DELETE_MODE:
			connection.setRequestMethod("POST");
			connection.addRequestProperty("X-OP", "Delete");
		default:
			break;
		}

		if (headerValues != null) {
			Map<String, String> headerValues = this.headerValues;
			for (String header : headerValues.keySet()) {
				connection.setRequestProperty(header, headerValues.get(header));
			}
		}

		connection.setInstanceFollowRedirects(true);
		System.out.println("byte:"+inputBuffer.size() );
		if (inputBuffer != null && inputBuffer.size() > 0) {
			connection.getOutputStream().write(inputBuffer.toByteArray());
		}
		connection.connect();
	}

	public boolean isConnected() {
		return connection != null;
	}

	public boolean isSuccessful() throws IOException {
		if (connection != null) {
			int code = connection.getResponseCode();
			return (code >= 200 && code < 400)
					|| (connection.getUseCaches() && code == -1);

		}
		return false;
	}

	public static boolean isSuccess(String surl) throws IOException {
		URL url = new URL(surl);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.connect();
		int code = connection.getResponseCode();
		return (code >= 200 && code < 400)
				|| (connection.getUseCaches() && code == -1);
	}

	public boolean isLatest() {
		if (connection != null) {
			try {
				int code = connection.getResponseCode();
				return (code == 304);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return false;
	}

	public String getLastModified() {
		if (connection != null) {
			return connection.getHeaderField("Last-Modified");
		}
		return null;
	}

	public String getETag() {
		if (connection != null) {
			return connection.getHeaderField("Etag");
		}
		return null;
	}

	public String getContentType() {
		if (connection != null) {
			return connection.getContentType();
		}
		return null;
	}

	public int getContentLength() {
		if (connection != null) {
			return connection.getContentLength();
		}
		return 0;
	}

	public String getContentEncoding() {
		if (connection != null) {
			return connection.getContentEncoding();
		}
		return null;
	}

	public int getResponseCode() throws IOException {
		if (connection != null) {
			return connection.getResponseCode();
		}
		return -1;
	}

	public String getHeader(String header) {
		if (connection != null) {
			return connection.getHeaderField(header);
		}
		return null;
	}

	public InputStream getBody() throws IOException {
		if (connection != null) {
			String contentEncoding = connection.getContentEncoding();
			if (this.isSuccessful()) {
				if ("gzip".equals(contentEncoding)) {
					return new GZIPInputStream(connection.getInputStream());
				} else if ("deflate".equals(contentEncoding)) {
					return new InflaterInputStream(connection.getInputStream());
				} else {
					return connection.getInputStream();
				}
			} else {
				if ("gzip".equals(contentEncoding)) {
					return new GZIPInputStream(connection.getErrorStream());
				} else if ("deflate".equals(contentEncoding)) {
					return new InflaterInputStream(connection.getErrorStream());
				} else {
					return connection.getErrorStream();
				}
			}
		}
		return null;
	}

	public String getBodyAsString() {
		if (connection != null) {
			HttpURLConnection connection = this.connection;
			InputStreamReader reader = null;
			try {
				String contentEncoding = connection.getContentEncoding();
				String contentType = getContentType(connection.getContentType());
				if (this.isSuccessful()) {
					if ("gzip".equals(contentEncoding)) {
						reader = new InputStreamReader(new GZIPInputStream(
								connection.getInputStream()), contentType);
					} else if ("deflate".equals(contentEncoding)) {
						reader = new InputStreamReader(new InflaterInputStream(
								connection.getInputStream()), contentType);
					} else {
						reader = new InputStreamReader(
								connection.getInputStream(), contentType);
					}
				} else {
					InputStream is = connection.getErrorStream();
					if (is == null) {
						return null;
					}
					if ("gzip".equals(contentEncoding)) {
						reader = new InputStreamReader(new GZIPInputStream(is),
								contentType);
					} else if ("deflate".equals(contentEncoding)) {
						reader = new InputStreamReader(new InflaterInputStream(
								is), contentType);
					} else {
						reader = new InputStreamReader(is, contentType);
					}
				}
				StringBuilder builder = new StringBuilder();
				char[] buffer = new char[1024];
				int read;
				while ((read = reader.read(buffer)) > -1) {
					builder.append(buffer, 0, read);
				}
                System.out.println("Re BYte:"+builder.length());
				return builder.toString();
			} catch (UnsupportedEncodingException ex) {
				// ex.printStackTrace();
			} catch (IOException ex) {
				// ignore this error
			} finally {
				if (reader != null) {
					try {
						reader.close();
					} catch (IOException ex) {
						// ignore this error.
					}
				}
				// connection.disconnect();
				close();
			}
		}
		return null;
	}

	private String getContentType(String contentTypeString) {
		String contentType = contentTypeString;
		String charset = "GBK";
		if (contentType != null) {
			String[] values = contentType.split(";");
			for (String value : values) {
				value = value.trim();
				if (value.toLowerCase().startsWith("charset=")) {
					charset = value.substring("charset=".length());
				}
			}
			if (TextUtils.isEmpty(charset)) {
				charset = "GBK";
			}
		}
		return charset;
	}

	private void ensureHeaderValuesNotNull() {
		if (headerValues == null) {
			headerValues = new HashMap<String, String>();
		}
	}

	public void close() {
		if (inputBuffer != null) {
			try {
				inputBuffer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (connection != null) {
			connection.disconnect();
		}
	}
}
